package com.yb0os1.serve.impl;

import com.yb0os1.entity.Orders;
import com.yb0os1.entity.Top10;
import com.yb0os1.entity.TurnoverStatistics;
import com.yb0os1.entity.UserStatistics;
import com.yb0os1.mapper.OrderDetailMapper;
import com.yb0os1.mapper.OrderMapper;
import com.yb0os1.mapper.UserMapper;
import com.yb0os1.serve.ReportServe;
import com.yb0os1.vo.OrderReportVO;
import com.yb0os1.vo.SalesTop10ReportVO;
import com.yb0os1.vo.TurnoverReportVO;
import com.yb0os1.vo.UserRepoertVO;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
public class ReportServeImpl implements ReportServe {
    @Override
    public void exportData(HttpServletResponse response) {
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);
        // 30天内的营业额
        BigDecimal turnover =  orderMapper.getTurnover(begin,end);
        // 30天内新增用户量
        Integer newUserNumber = userMapper.getUser(begin,end);
        // 30天内有效订单
        Integer validOrders =  orderMapper.getOrders(begin,end,Orders.COMPLETED);
        // 30天内全部订单
        Integer allOrders =  orderMapper.getOrders(begin,end,null);
        // 30天内平均客单价
        BigDecimal unitPrice = turnover.divide(BigDecimal.valueOf(validOrders),2,RoundingMode.UP);
        // 30天订单完成率
        BigDecimal orderCompletionRate = BigDecimal.valueOf(validOrders).divide(BigDecimal.valueOf(allOrders),2,RoundingMode.UP);

        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("templates/运营数据报表模板.xlsx");
        try(
                XSSFWorkbook excel = new XSSFWorkbook(resourceAsStream);
                ServletOutputStream outputStream = response.getOutputStream();
        ) {
            XSSFSheet sheet = excel.getSheet("Sheet1");
            sheet.getRow(1).getCell(1).setCellValue("时间："+begin+"-"+end);
            sheet.getRow(3).getCell(2).setCellValue(String.valueOf(turnover));
            sheet.getRow(3).getCell(4).setCellValue(String.valueOf(orderCompletionRate));
            sheet.getRow(3).getCell(6).setCellValue(newUserNumber);
            sheet.getRow(4).getCell(2).setCellValue(validOrders);
            sheet.getRow(4).getCell(4).setCellValue(String.valueOf(unitPrice));

            OrderReportVO orderReportVO = ordersStatistics(begin, end);
            UserRepoertVO userRepoertVO = userStatistics(begin, end);
            TurnoverReportVO turnoverReportVO = turnoverStatistics(begin, end);

            String[] dates = orderReportVO.getDateList().split(",");
            String[] validOrderCountList = orderReportVO.getValidOrderCountList().split(",");
            String[] turnoverList = turnoverReportVO.getTurnoverList().split(",");
            String[] orderCountList = orderReportVO.getOrderCountList().split(",");
            String[] newUserList = userRepoertVO.getNewUserList().split(",");
            String[] completeRateList = new String[30];
            String[] unitPriceList = new String[30];
            for (int i = 0;i<orderCountList.length;++i) {
                String order = orderCountList[i];
                if (order.equals("0")){
                    completeRateList[i] = String.valueOf(0);
                    unitPriceList[i] = String.valueOf(0);
                }else{
                    BigDecimal turnoverOneday = new BigDecimal(turnoverList[i]);
                    BigDecimal validOrderCount = new BigDecimal(validOrderCountList[i]);
                    BigDecimal orderNumber = new BigDecimal(order);
                    unitPriceList[i] = String.valueOf(turnoverOneday.divide(validOrderCount,2,RoundingMode.UP));
                    completeRateList[i] = String.valueOf(validOrderCount.divide(orderNumber,2,RoundingMode.UP));
                }
            }
            for (int i = 7;i<37;++i){
                sheet.getRow(i).getCell(1).setCellValue(dates[i-7]);
                sheet.getRow(i).getCell(2).setCellValue(turnoverList[i-7]);
                sheet.getRow(i).getCell(3).setCellValue(validOrderCountList[i-7]);
                sheet.getRow(i).getCell(4).setCellValue(completeRateList[i-7]);
                sheet.getRow(i).getCell(5).setCellValue(unitPriceList[i-7]);
                sheet.getRow(i).getCell(6).setCellValue(newUserList[i-7]);
            }

            excel.write(outputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Override
    public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {
        List<Top10> top10s =  orderDetailMapper.getTop10(begin,end);
        List<String>nameList = new ArrayList<>();
        List<Integer>numberList = new ArrayList<>();
        for (Top10 top10 : top10s) {
            nameList.add(top10.getName());
            numberList.add(top10.getTotal());
        }

        return SalesTop10ReportVO.builder()
                .nameList(StringUtils.join(nameList,","))
                .numberList(StringUtils.join(numberList,","))
                .build();
    }

    @Autowired
    private OrderMapper orderMapper;
    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        List<LocalDate>dateList = new ArrayList<>();
        List<Integer>validOrderCountList = new ArrayList<>();
        List<Integer>orderCountList = new ArrayList<>();
        while (!begin.isAfter(end)){
            dateList.add(begin);
            Integer validOrderCount =  orderMapper.getOrdersStatistics(begin, Orders.COMPLETED,true);
            validOrderCountList.add(validOrderCount);
            Integer orderCount =  orderMapper.getOrdersStatistics(begin, null,true);
            orderCountList.add(orderCount);
            begin = begin.plusDays(1);
        }
        Integer totalOrderCount = orderMapper.getOrdersStatistics(null, null,false);
        Integer validOrderCount = orderMapper.getOrdersStatistics(null, Orders.COMPLETED,false);
        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList,","))
                .validOrderCountList(StringUtils.join(validOrderCountList,","))
                .orderCountList(StringUtils.join(orderCountList,","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(BigDecimal.valueOf(validOrderCount).divide(BigDecimal.valueOf(totalOrderCount),4, RoundingMode.HALF_UP))
                .build();
    }

    @Autowired
    private UserMapper userMapper;
    @Override
    public UserRepoertVO userStatistics(LocalDate begin, LocalDate end) {
        List<UserStatistics> userStatisticsList =  userMapper.getUserStatistics(begin,end);
        List<LocalDate>dataList = new ArrayList<>();
        List<Integer> totalUser = new ArrayList<>();
        List<Integer> newUser = new ArrayList<>();
        while (!begin.isAfter(end)) {
            dataList.add(begin);
            if (!userStatisticsList.isEmpty()){
                UserStatistics user = userStatisticsList.get(0);
                if(begin.isEqual(user.getDate())){
                    newUser.add(user.getNewUserNumber());
                    userStatisticsList.remove(0);
                }else{
                    newUser.add(0);
                }
            }else{
                newUser.add(0);
            }
            Integer total =  orderMapper.getTotalNumber(begin);
            totalUser.add(total);
            begin = begin.plusDays(1);
        }
        return UserRepoertVO.builder()
                .dateList(StringUtils.join(dataList,","))
                .newUserList(StringUtils.join(newUser,","))
                .totalUserList(StringUtils.join(totalUser,","))
                .build();
    }

    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end) {
        //构建dataList
        //构建营业额
        List<LocalDate>dataList = new ArrayList<>();
        List<BigDecimal> moneys = new ArrayList<>();
        List<TurnoverStatistics> turnovers =  orderMapper.getTurnoverStatistics(begin,end);
        while (!begin.isAfter(end)){
            dataList.add(begin);
            if (!turnovers.isEmpty()){
                TurnoverStatistics first = turnovers.get(0);
                if(begin.isEqual(first.getDate())){
                    moneys.add(first.getMoney());
                    turnovers.remove(0);
                }else{
                    moneys.add(BigDecimal.valueOf(0));
                }
            }else{
                moneys.add(BigDecimal.valueOf(0));
            }
            begin = begin.plusDays(1);
        }

        return TurnoverReportVO.builder()
                .dateList(StringUtils.join(dataList,","))
                .turnoverList(StringUtils.join(moneys,","))
                .build();
    }
}
